package com.fable.sp.core.service.impl;

import com.fable.sp.core.widget.WidgetSession;
import com.google.common.collect.Maps;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpSession;
import java.util.Enumeration;
import java.util.Map;
import java.util.Vector;

/**
 * .
 *
 * @author stormning on 16/8/9.
 */
public class WidgetSessionImpl implements WidgetSession {
    private HttpSession session;
    private String widgetScopePrefix;
    private boolean inValid = false;


    public WidgetSessionImpl(HttpSession session, String widgetName) {
        this.session = session;
        this.widgetScopePrefix = widgetName + "_";
    }

    @Override
    public Object getAttribute(String name) {
        return getAttribute(name, WIDGET_SCOPE);
    }

    @Override
    public Object getAttribute(String name, int scope) {
        return session.getAttribute(genAttrName(name, scope));
    }

    @Override
    public Enumeration<String> getAttributeNames() {
        return getAttributeNames(WIDGET_SCOPE);
    }

    @Override
    public Enumeration<String> getAttributeNames(int scope) {
        Enumeration<String> attributeNames = session.getAttributeNames();
        Vector<String> names = new Vector<>();
        boolean isAppScope = scope == APPLICATION_SCOPE;
        while (attributeNames.hasMoreElements()) {
            String name = attributeNames.nextElement();
            boolean widgetAttr = StringUtils.startsWithIgnoreCase(name, widgetScopePrefix);
            if (isAppScope) {
                if (!widgetAttr) {
                    names.add(name);
                }
            } else {
                if (widgetAttr) {
                    names.add(name.replaceFirst(widgetScopePrefix, ""));
                }
            }
        }
        return names.elements();
    }

    @Override
    public long getCreationTime() {
        return session.getCreationTime();
    }

    @Override
    public String getId() {
        return session.getId();
    }

    @Override
    public long getLastAccessedTime() {
        return session.getLastAccessedTime();
    }

    @Override
    public int getMaxInactiveInterval() {
        return session.getMaxInactiveInterval();
    }

    @Override
    public void setMaxInactiveInterval(int interval) {
        session.setMaxInactiveInterval(interval);
    }

    @Override
    public void invalidate() {
        session.invalidate();
        this.inValid = true;
    }

    @Override
    public boolean isNew() {
        return session.isNew();
    }

    @Override
    public void removeAttribute(String name) {
        removeAttribute(name, WIDGET_SCOPE);
    }

    @Override
    public void removeAttribute(String name, int scope) {
        session.removeAttribute(genAttrName(name, scope));
    }

    @Override
    public void setAttribute(String name, Object value) {
        setAttribute(name, value, WIDGET_SCOPE);
    }

    @Override
    public void setAttribute(String name, Object value, int scope) {
        session.setAttribute(genAttrName(name, scope), value);
    }

    private String genAttrName(String name, int scope) {
        return scope == WIDGET_SCOPE ? widgetScopePrefix + name : name;
    }

    @Override
    public Map<String, Object> getAttributeMap() {
        return getAttributeMap(WIDGET_SCOPE);
    }

    @Override
    public Map<String, Object> getAttributeMap(int scope) {
        Map<String, Object> map = Maps.newHashMap();
        Enumeration<String> attributeNames = session.getAttributeNames();
        boolean isAppScope = scope == APPLICATION_SCOPE;
        while (attributeNames.hasMoreElements()) {
            String name = attributeNames.nextElement();
            boolean widgetAttr = StringUtils.startsWithIgnoreCase(name, widgetScopePrefix);
            if (isAppScope) {
                if (!widgetAttr) {
                    map.put(name, getAttribute(name, scope));
                }
            } else {
                if (widgetAttr) {
                    name = name.replaceFirst(widgetScopePrefix, "");
                    map.put(name, getAttribute(name, scope));
                }
            }
        }
        return map;
    }

    public boolean isInValid() {
        return inValid;
    }

    public void setInValid(boolean inValid) {
        this.inValid = inValid;
    }
}
